import React, { Component } from 'react'
import { Spin, message } from 'antd'
import paramUtil from '@/utils/paramUtil.js'
import { myEval } from '@/utils/usualUtil'
import { CloseCircleFilled } from '@ant-design/icons'
import _ from 'lodash'
import './index.css'

/**
 * 多选框组件
 * @author liu_jshan
 * @version 1.1
 * @props {
 *  paramCode：参数code，必须 string
 *  paramItem：参数内容，非必须，对象{
 *      id：参数项唯一标识 必须
 *      code：参数项的值 必须
 *      content：参数项展示的内容
 *  }
 *  value：默认选中的值 数组 非必须
 *  style：样式
 *  disabled: 是否禁用，boolean
 *  onChange: 值变化的回调方法，function onChange(value)
 *  hiddenClearButton: 隐藏清除按钮，boolean
 *  suffixName：自定义后缀，string or 组件，是在现有后缀的基础上增加，不是替换
 *  prefixName: 前缀，对象 {
 *    content: 前缀内容, string or 图标组件
 *    style: 前缀样式
 *  } 
 *  rules：校验，array
 *    rules：[
 *      {
 *        validate: 校验的方法，需要返回布尔类型，function 参数为value
 *        failMessage: 校验不通过的提示信息，string
 *        successMessage: 校验通过的提示信息，string 非必须
 *      }
 *    ]
 * }
 */
class CheckBoxWidget extends Component {

    constructor(props) {
        super(props)
        this.state = {
            param: {
                paramItem: [],
                code: null
            },
            loading: true,
            value: [],
            lastValue: [], //原来的值
            validateMessage: '',//校验信息字符串
            validateMessageArr: [],//校验信息数组
            validateSuccess: true, //校验是否通过
            prefixDisplay: false,
            suffixDisplay: true
        }
    }

    async componentDidMount() {
        let { paramCode, paramItem, value } = this.props
        if (value && typeof value === 'string') {
            let newValue = myEval(this, value)
            if (Array.isArray(newValue) === true) value = newValue
            else value = []
        } else if (Array.isArray(value) === false) {
            value = []
        }
        let param = {}
        if (paramCode && paramItem) { //code和item都存在
            param = {
                paramItem,
                code: paramCode
            }
        } else if (paramCode && !paramItem) { //只存在code需要查询参数
            const response = await paramUtil.get(paramCode)
            if (response) {
                param = {
                    code: paramCode,
                    paramItem: response.children
                }
            }
        } else {
            message.warning('多选框尚未配置参数项')
        }

        let prefixDisplay = this.props.prefixName ? true : false //前缀显隐
        let suffixDisplay = this.props.disabled !== true && (this.props.suffixName || this.props.hiddenclearButton !== true) ? true : false

        await new Promise(resolve => {
            this.setState({
                param,
                value: value,
                prefixDisplay,
                suffixDisplay
            }, resolve)
        })
        if (param.code && param.paramItem) {
            await new Promise(resolve => { this.setState({ loading: false }, resolve) })
        }
    }

    /**
     * 组件值变化时调用
     * @param {*} valueArray 变化后的值
     * @param {*} callPropsChange 是否调用props的onChange回调函数，默认true
     */
    onChange = async (valueArray, callPropsChange = true) => {
        let lastValue = this.state.value
        await new Promise(resolve => {
            this.setState({
                value: valueArray,
                lastValue
            }, resolve)
        })

        await this.validateRules()

        if (callPropsChange && this.props.onChange && typeof this.props.onChange === 'function') {
            await this.props.onChange(valueArray)
        }
    }

    validateRules = async () => {
        const value = this.state.value
        let validateMessageArr = []
        let validateMessage = ''
        let validateSuccess = true
        const { rules } = this.props
        if (rules && Array.isArray(rules) && rules.length > 0) {
            for (let i = 0; i < rules.length; i++) {
                const { validate, failMessage, successMessage } = rules[i]
                if (validate && typeof validate === 'function') {
                    let res = await validate(value)
                    if (res === false) {
                        if (validateSuccess === true && validateMessageArr.length > 0) { //之前校验的都是正确的
                            validateMessageArr = []
                        }
                        validateMessageArr.push(failMessage ? failMessage : '请配置校验提示信息！')
                        validateSuccess = false
                    } else if (res === true && validateSuccess === true && successMessage) {
                        validateMessageArr.push(successMessage)
                    }
                }
            }
            validateMessage = validateMessageArr.join('; ')
        }

        await new Promise(resolve => {
            this.setState({
                validateMessage,
                validateMessageArr,
                validateSuccess
            }, resolve)
        })

        return validateSuccess
    }

    render() {
        if (this.state.loading === true) return <Spin />
        const { param, value } = this.state
        return (
            <div
                style={this.props.style}
                className='checkBoxWidget-main'
            >
                <div className='checkBoxWidget-input'>
                    {
                        this.state.prefixDisplay === false ? '' :
                            <div className='checkBoxWidget-prefix' style={this.props.prefixName.style}>
                                {this.props.prefixName.content}
                            </div>
                    }
                    <div className='checkBoxWidget-content'>
                        {
                            param.paramItem.map(item => {
                                return (
                                    <div key={item.id} className='checkBoxWidget-item'>
                                        <input
                                            type='checkbox'
                                            value={item.code}
                                            name={param.code}
                                            onChange={async event => {
                                                const { checked, value } = event.target
                                                let valueArray = _.cloneDeep(this.state.value)
                                                if (checked === true) {
                                                    valueArray.push(value)
                                                    valueArray = Array.from(new Set(valueArray))
                                                } else {
                                                    valueArray = valueArray.filter(item => item !== value)
                                                }
                                                await this.onChange(valueArray)
                                            }}
                                            checked={value.indexOf(item.code) > -1 ? true : false}
                                            disabled={this.props.disabled}
                                        />{item.content}
                                    </div>
                                )
                            })
                        }
                    </div>
                    {
                        this.state.suffixDisplay === false ? '' :
                            <div className='checkBoxWidget-suffix'>
                                {
                                    this.props.hiddenClearButton === true ? '' :
                                        <CloseCircleFilled
                                            onClick={async () => {
                                                await new Promise(resolve => {
                                                    this.setState({
                                                        lastValue: [],
                                                        value: [],
                                                        validateMessage: '',
                                                        validateMessageArr: [],
                                                        validateSuccess: true
                                                    }, resolve)
                                                })
                                                if (this.props.onChange && typeof this.props.onChange === 'function') {
                                                    await this.props.onChange()
                                                }
                                            }}
                                        ></CloseCircleFilled>
                                }
                                {this.props.suffixName ? this.props.suffixName : ''}
                            </div>
                    }
                    <div className='RadioWidget-messageDiv'
                        style={{ color: this.state.validateSuccess === true ? 'var(--ordinary-font-color)' : 'var(--danger-font-color)' }}
                    >
                        {this.state.validateMessage}
                    </div>
                </div>
            </div>
        )
    }
}

export default CheckBoxWidget
